/*
 * CgObject.c
 *
 *  Created on: 2012/06/07
 *      Author: guanxiaoying
 */
#include "../coredef.h"
#include "../cc/cc.h"
#include "cg.h"
static CHAR  strVarNameBuf[1024];
static U4 cg_solveSubVariable( AST astParentVari, PSZ parentName );

static AST cg_ConvertMember( AST astMemSym ){
	AST astNewMember;
	AST astType = stSymbolInfoAccess.type.get( astMemSym );
	stMemberSymbolAccess.alloc(1);
	astNewMember = stMemberSymbolAccess.getMax();
	stMemberSymbolAccess.codeScp.set( astNewMember, stSymbolInfoAccess.codeScp.get( astMemSym ) );
	stMemberSymbolAccess.memOffset.set( astNewMember, stSymbolInfoAccess.memOffset.get( astMemSym ) );
	stMemberSymbolAccess.name.set( astNewMember, stSymbolInfoAccess.name.get( astMemSym ) );
	astType = CG_ConvertTypeInfo(astType);
	stMemberSymbolAccess.type.set( astNewMember, astType );
	return astNewMember;
}
static AST cg_ConvertParameter( AST astMemSym ){
	AST astNewMember;
	AST astType = stSymbolInfoAccess.type.get( astMemSym );
	stMemberSymbolAccess.alloc(1);
	astNewMember = stMemberSymbolAccess.getMax();
	stMemberSymbolAccess.codeScp.set( astNewMember, stSymbolInfoAccess.codeScp.get( astMemSym ) );
	stMemberSymbolAccess.name.set( astNewMember, stSymbolInfoAccess.name.get( astMemSym ) );
	astType = CG_ConvertTypeInfo(astType);
	stMemberSymbolAccess.type.set( astNewMember, astType );
	stMemberSymbolAccess.symClass.set( astNewMember, stSymbolInfoAccess.symClass.get( astMemSym ) );
	return astNewMember;
}
static AST cg_ConvertEnumConst( AST astMemSym ){
	AST astNewMember;
	AST astType = stSymbolInfoAccess.type.get( astMemSym );
	stMemberSymbolAccess.alloc(1);
	astNewMember = stMemberSymbolAccess.getMax();
	stMemberSymbolAccess.codeScp.set( astNewMember, stSymbolInfoAccess.codeScp.get( astMemSym ) );
	stMemberSymbolAccess.name.set( astNewMember, stSymbolInfoAccess.name.get( astMemSym ) );
	astType = CG_ConvertTypeInfo(astType);
	stMemberSymbolAccess.type.set( astNewMember, astType );
	stMemberSymbolAccess.value.set( astNewMember,
			CG_ConvertConstant( stSymbolInfoAccess.value.get( astMemSym ) ) );
	return astNewMember;
}
AST CG_ConvertMembers( AST astMemSym ){
	U2 kind;
	if( astMemSym == 0 ){
		return 0;
	}
	TRY;
	kind = stSymbolInfoAccess.kind.get( astMemSym );
	if( kind == SYMBOL_KIND_MEMBER ){
		return cg_ConvertMember( astMemSym );
	}else if( kind == SYMBOL_KIND_PARAM  ){
		return cg_ConvertParameter( astMemSym );
	}else if( kind == SYMBOL_KIND_ENUMCONST  ){
		return cg_ConvertEnumConst( astMemSym );
	}
	CATCH(0);
	return 0;
}
AST CG_ConvertToFunction( AST astSym ){
	U2 kind;
	BOOL bRet;
	AST astCCType;
	AST astRelation;
	AST astLinkType;
	AST astFunction;

	if( astSym == 0 ){
		return 0;
	}
	kind = stSymbolInfoAccess.kind.get( astSym );
	if( kind != SYMBOL_KIND_FUNCTION ){
		return 0;
	}
	bRet = stCgSymbolRelationAccess.findMemSymbol( astSym, &astRelation );
	if( bRet == TRUE ){
		astFunction = stCgSymbolRelationAccess.linkedSym.get( astRelation );
		if( astFunction != 0 ){
			return astFunction;
		}
	}
	astCCType = stSymbolInfoAccess.type.get( astSym );
	bRet = stCgTypeRelationAccess.findCcType( astCCType, &astRelation );
	if( bRet == FALSE || astRelation == 0 ){
		astLinkType = CG_ConvertTypeInfo(astCCType);
	}else{
		astLinkType = stCgTypeRelationAccess.linkedType.get( astRelation );
	}


	stFunctionInfoAccess.alloc(1);
	astFunction = stFunctionInfoAccess.getMax();
	stFunctionInfoAccess.codeScp.set( astFunction, stSymbolInfoAccess.codeScp.get( astSym ));
	stFunctionInfoAccess.linkage.set( astFunction, stSymbolInfoAccess.linkage.get( astSym ));
	stFunctionInfoAccess.name.set( astFunction, stSymbolInfoAccess.name.get( astSym ));
	stFunctionInfoAccess.symClass.set( astFunction, stSymbolInfoAccess.symClass.get( astSym ));
	stFunctionInfoAccess.type.set( astFunction, astLinkType );

	astRelation = stCgSymbolRelationAccess.addMemSymbol( astSym );
	stCgSymbolRelationAccess.linkedSym.set( astRelation, astFunction );

	return astFunction;
}
static U4 cg_solveSubOfUnionType( AST astParentVari, PSZ parentName ){
	AST astType;
	AST astVari;
	AST astPre;
	AST astMember;
	PSZ memberArea;
	PSZ memberName;
	U4  eleSize=0;
	U4  size=0;

	astType = stVariableInfoAccess.type.get( astParentVari );
	astMember = stLinkTypeInfoAccess.memChain.get( astType );
	astPre = 0;
	size = 0;
	while( astMember ){
		memberName = stMemberSymbolAccess.name.get( astMember );
		if( memberName == NULL || memberName[0] == '\0' ){
			astMember = stMemberSymbolAccess.next.get( astMember );
			continue;
		}
		strVarNameBuf[0]='\0';
		if( parentName != NULL ){
			strcpy( strVarNameBuf, parentName );
		}
		memberArea =&strVarNameBuf[strlen(strVarNameBuf)];

		if( memberName != NULL ){
			strcpy( memberArea, "." );
			strcat( memberArea, memberName );
		}

		astType = stMemberSymbolAccess.type.get( astMember );
		stVariableInfoAccess.alloc(1);
		astVari = stVariableInfoAccess.getMax();
		stVariableInfoAccess.codeScp.set( astVari, stMemberSymbolAccess.codeScp.get( astMember ));
		stVariableInfoAccess.parent.set( astVari, astParentVari );
		stVariableInfoAccess.type.set( astVari, astType );
		stVariableInfoAccess.name.set( astVari, strVarNameBuf );
		eleSize = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ) );
		stVariableInfoAccess.offset.set( astVari, 0 );
		stVariableInfoAccess.length.set( astVari, eleSize );
		if( size < eleSize ){
			size = eleSize;
		}
		if( astPre == 0 ){
			stVariableInfoAccess.parent.set( astVari, astParentVari );
			stVariableInfoAccess.child.set( astParentVari, astVari );
		}else{
			stVariableInfoAccess.next.set( astPre, astVari );
			stVariableInfoAccess.prev.set( astVari, astPre );
		}
		astMember = stMemberSymbolAccess.next.get( astMember );
	}
	return size;
}
static U4 cg_solveSubOfStructType( AST astParentVari, PSZ parentName ){
	AST astType;
	AST astVari;
	AST astPre;
	AST astMember;
	U4  eleSize=0;
	U4  size=0;
	PSZ memberArea;
	PSZ memberName;

	astType = stVariableInfoAccess.type.get( astParentVari );
	astMember = stLinkTypeInfoAccess.memChain.get( astType );
	astPre = 0;
	size = 0;
	while( astMember ){
		memberName = stMemberSymbolAccess.name.get( astMember );
		if( memberName == NULL || memberName[0] == '\0' ){
			astMember = stMemberSymbolAccess.next.get( astMember );
			continue;
		}
		strVarNameBuf[0]='\0';
		if( parentName != NULL ){
			strcpy( strVarNameBuf, parentName );
		}
		memberArea = &strVarNameBuf[strlen(strVarNameBuf)];

		if( memberName != NULL ){
			strcpy( memberArea, "." );
			strcat( memberArea, memberName );
		}

		astType = stMemberSymbolAccess.type.get( astMember );
		stVariableInfoAccess.alloc(1);
		astVari = stVariableInfoAccess.getMax();
		stVariableInfoAccess.codeScp.set( astVari, stMemberSymbolAccess.codeScp.get( astMember ));
		stVariableInfoAccess.parent.set( astVari, astParentVari );
		stVariableInfoAccess.type.set( astVari, astType );
		stVariableInfoAccess.name.set( astVari, strVarNameBuf );
		eleSize = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get(astVari) );
		stVariableInfoAccess.offset.set( astVari, size );
		stVariableInfoAccess.length.set( astVari, eleSize );
		size += eleSize;
		if( astPre == 0 ){
			stVariableInfoAccess.parent.set( astVari, astParentVari );
			stVariableInfoAccess.child.set( astParentVari, astVari );
		}else{
			stVariableInfoAccess.next.set( astPre, astVari );
			stVariableInfoAccess.prev.set( astVari, astPre );
		}
		astPre = astVari;
		astMember = stMemberSymbolAccess.next.get( astMember );
	}
	return size;
}
static U4 cg_solveSubOfArrayType( AST astParentVari, PSZ parentName ){
	AST astType;
	AST astVari;
	AST astPre;
	U4  eleSize=0;
	U4  size=0;
	U4  cnt=0;
	PSZ arrayArea;
	BOOL bVariSize=FALSE;


	astType = stVariableInfoAccess.type.get( astParentVari );
	size = stLinkTypeInfoAccess.size.get( astType );
	if( stLinkTypeInfoAccess.bVariableSize.get( astType )){
		bVariSize = TRUE;
	}
	astType = stLinkTypeInfoAccess.elementType.get( astType );

	strVarNameBuf[0]='\0';
	if( parentName != NULL ){
		strcpy( strVarNameBuf, parentName );
	}
	arrayArea = &strVarNameBuf[strlen(strVarNameBuf)];
	if( bVariSize && size == 0 ){
		strcpy( arrayArea, "[N]" );
	}else{
		strcpy( arrayArea, "[0]" );
	}

	stVariableInfoAccess.alloc(1);
	astVari = stVariableInfoAccess.getMax();
	stVariableInfoAccess.codeScp.set( astVari, stVariableInfoAccess.codeScp.get( astParentVari ));
	stVariableInfoAccess.parent.set( astVari, astParentVari );
	stVariableInfoAccess.type.set( astVari, astType );
	stVariableInfoAccess.name.set( astVari, strVarNameBuf );
	eleSize = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ) );
	stVariableInfoAccess.offset.set( astVari, cnt*eleSize );
	stVariableInfoAccess.length.set( astVari, eleSize );
	stVariableInfoAccess.parent.set( astVari, astParentVari );
	stVariableInfoAccess.child.set( astParentVari, astVari );
	astPre = astVari;


	cnt = 1;
	while( cnt < size ){
		strVarNameBuf[0]='\0';
		if( parentName != NULL ){
			strcpy( strVarNameBuf, parentName );
		}
		arrayArea = &strVarNameBuf[strlen(strVarNameBuf)];
		sprintf( arrayArea, "[%lu]", cnt );
		stVariableInfoAccess.alloc(1);
		astVari = stVariableInfoAccess.getMax();
		stVariableInfoAccess.codeScp.set( astVari, stVariableInfoAccess.codeScp.get( astParentVari ));
		stVariableInfoAccess.parent.set( astVari, astParentVari );
		stVariableInfoAccess.type.set( astVari, astType );
		stVariableInfoAccess.name.set( astVari, strVarNameBuf );
		eleSize = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ) );
		stVariableInfoAccess.offset.set( astVari, cnt*eleSize );
		stVariableInfoAccess.length.set( astVari, eleSize );
		stVariableInfoAccess.next.set( astPre, astVari );
		stVariableInfoAccess.prev.set( astVari, astPre );
		astPre = astVari;
		cnt++;
	}
	return eleSize*cnt;
}
static U4 cg_solveSubVariable( AST astParentVari, PSZ parentName ){
	AST astLinkType;
	U4  subSize=0;
	TRY;

	astLinkType = stVariableInfoAccess.type.get( astParentVari );
	switch( stLinkTypeInfoAccess.typeKind.get( astLinkType ) ){
		case TYPEKIND_BASIC			:	/* 通常の型			*/
			subSize = stLinkTypeInfoAccess.size.get( astLinkType );
			break;
		case TYPEKIND_ARRAY			:	/* 配列				*/
			subSize = cg_solveSubOfArrayType( astParentVari, parentName );
			break;
		case TYPEKIND_POINTER		:	/* ﾎﾟｲﾝﾀ			*/
			subSize = stLinkTypeInfoAccess.size.get( astLinkType );
			break;
		case TYPEKIND_STRUCT		:	/* 構造体			*/
			subSize = cg_solveSubOfStructType( astParentVari, parentName );
			break;
		case TYPEKIND_UNION			:	/* 共用体			*/
			subSize = cg_solveSubOfUnionType( astParentVari, parentName );
			break;
		case TYPEKIND_ENUM			:	/* 列挙型			*/
			subSize = stLinkTypeInfoAccess.size.get( astLinkType );
			break;
		case TYPEKIND_FUNCTION		:	/* 関数(実体)			*/
			break ;
		case TYPEKIND_BITFIELD		:	/* BitField型			*/
			subSize = stLinkTypeInfoAccess.size.get( stLinkTypeInfoAccess.elementType.get( astLinkType ) );
			break;
	}
	CATCH(0);
	return subSize;
}
AST CG_ConvertToVariable( AST astSym ){
	AST astCCType;
	AST astRelation;
	AST astLinkType;
	AST astDataSection;
	AST astVari;
	AST astLinkage;
	U4  offset;
	U4  size;
	U2 kind;
	AST astChain;
	BOOL bRet;
	if( astSym == 0 ){
		return 0;
	}
	kind = stSymbolInfoAccess.kind.get( astSym );
	if( kind != SYMBOL_KIND_VARIABLE ){
		return 0;
	}
	astLinkage = stSymbolInfoAccess.linkage.get( astSym );
	if( astLinkage > 0 ){
		/*debug,13/1/30,S*/
		//astSym = stCCLinkageAccess.definitionSym.get( astLinkage );
		//if( astSym == 0 ){
		/*debug,13/1/30,E*/
			astChain = stCCLinkageAccess.definitionChain.get( astLinkage );
			if( astChain == 0 ){
				astChain = stCCLinkageAccess.tenDeclChain.get( astLinkage );
			}
			if( astChain == 0 ){
				astChain = stCCLinkageAccess.allChain.get( astLinkage );
			}
			astSym = stUniteChainAccess.parameter_sym.get( astChain );
		//}
	}
	bRet = stCgSymbolRelationAccess.findMemSymbol( astSym, &astRelation );
	if( bRet == TRUE ){
		astVari = stCgSymbolRelationAccess.linkedSym.get( astRelation );
		if( astVari != 0 ){
			return astVari;
		}
	}
	astCCType = stSymbolInfoAccess.type.get( astSym );
	bRet = stCgTypeRelationAccess.findCcType( astCCType, & astRelation );
	if( bRet == FALSE || astRelation == 0 ){
		astLinkType = CG_ConvertTypeInfo(astCCType);
	}else{
		astLinkType = stCgTypeRelationAccess.linkedType.get( astRelation );
	}

	astDataSection = CG_getVariDataSection( stSymbolInfoAccess.dataSection.get( astSym ) );

	stVariableInfoAccess.alloc(1);
	astVari = stVariableInfoAccess.getMax();
	stVariableInfoAccess.codeScp.set( astVari, stSymbolInfoAccess.codeScp.get( astSym ));
	stVariableInfoAccess.dataSection.set( astVari, astDataSection );
	stVariableInfoAccess.linkage.set( astVari, astLinkage );
	stVariableInfoAccess.name.set( astVari, stSymbolInfoAccess.name.get( astSym ));
	stVariableInfoAccess.symClass.set( astVari, stSymbolInfoAccess.symClass.get( astSym ));
	stVariableInfoAccess.type.set( astVari, astLinkType );
	size = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ) );
	offset = CG_dataSectionAddNew( astDataSection, size );
	stVariableInfoAccess.offset.set( astVari, offset );
	stVariableInfoAccess.length.set( astVari, size );

	astRelation = stCgSymbolRelationAccess.addMemSymbol( astSym );
	stCgSymbolRelationAccess.linkedSym.set( astRelation, astVari );

	return astVari;
}
AST CG_ConvertToTemporaryVariable( AST astSym ){
	AST astCCType;
	AST astRelation;
	AST astLinkType;
	AST astVari;
	U4  size;
	BOOL bRet;
	if( astSym == 0 ){
		return 0;
	}
	bRet = stCgSymbolRelationAccess.findMemSymbol( astSym, &astRelation );
	if( bRet == TRUE ){
		astVari = stCgSymbolRelationAccess.linkedSym.get( astRelation );
		if( astVari != 0 ){
			return astVari;
		}
	}
	astCCType = stSymbolInfoAccess.type.get( astSym );
	bRet = stCgTypeRelationAccess.findCcType( astCCType, & astRelation );
	if( bRet == FALSE || astRelation == 0 ){
		astLinkType = CG_ConvertTypeInfo(astCCType);
	}else{
		astLinkType = stCgTypeRelationAccess.linkedType.get( astRelation );
	}
	stVariableInfoAccess.alloc(1);
	astVari = stVariableInfoAccess.getMax();
	stVariableInfoAccess.codeScp.set( astVari, stSymbolInfoAccess.codeScp.get( astSym ));
	stVariableInfoAccess.name.set( astVari, stSymbolInfoAccess.name.get( astSym ));
	stVariableInfoAccess.symClass.set( astVari, stSymbolInfoAccess.symClass.get( astSym ));
	stVariableInfoAccess.type.set( astVari, astLinkType );
	size = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ) );
	stVariableInfoAccess.offset.set( astVari, 0 );
	stVariableInfoAccess.length.set( astVari, size );


	astRelation = stCgSymbolRelationAccess.addMemSymbol( astSym );
	stCgSymbolRelationAccess.linkedSym.set( astRelation, astVari );

	return astVari;
}
static PSZ cg_setExpressionLabel(AST astExp) {
	static CHAR szELabel[64];
	AST astCodeScope = stExpressionAccess.codeScp.get( astExp );
	sprintf( szELabel, "_Compound_Literals_%ld_%ld_%ld", astExp,
			stCoreCodeScpAccess.startLine.get( astCodeScope ),
			stCoreCodeScpAccess.endLine.get( astCodeScope ));
	return szELabel;
}
AST CG_ConvertToTempVari_CompoundLiterals( AST astExp ){
	AST astCCType;
	AST astRelation;
	AST astLinkType;
	AST astVari;
	U4  size;
	BOOL bRet;


	astCCType = stExpressionAccess.type.get( astExp );
	bRet = stCgTypeRelationAccess.findCcType( astCCType, & astRelation );
	if( bRet == FALSE || astRelation == 0 ){
		astLinkType = CG_ConvertTypeInfo(astCCType);
	}else{
		astLinkType = stCgTypeRelationAccess.linkedType.get( astRelation );
	}
	stVariableInfoAccess.alloc(1);
	astVari = stVariableInfoAccess.getMax();
	stVariableInfoAccess.codeScp.set( astVari, stExpressionAccess.codeScp.get( astExp ));
	stVariableInfoAccess.name.set( astVari, cg_setExpressionLabel( astExp ));
	stVariableInfoAccess.type.set( astVari, astLinkType );
	size = cg_solveSubVariable( astVari, stVariableInfoAccess.name.get( astVari ));
	stVariableInfoAccess.offset.set( astVari, 0 );
	stVariableInfoAccess.length.set( astVari, size );
	return astVari;
}
AST CG_GetStUnMember( AST astVari, AST astSym ){
	PSZ pszSymName = stSymbolInfoAccess.name.get( astSym );
	PSZ pszVariName;
	AST astChildVari;

	astChildVari = stVariableInfoAccess.child.get( astVari );
	while( astChildVari ){
		pszVariName = stVariableInfoAccess.name.get( astChildVari );
		if( 0 == strcmp( pszVariName, pszSymName )){
			break;
		}
		astChildVari = stVariableInfoAccess.next.get( astChildVari );
	}
	return astChildVari;
}
AST CG_GetArrayMember( AST astVari, AST astConstant ){
	VARVALUE value = CcValueGetInteger(astConstant);
	AST astChildVari;
	if( value.sign != 1 ){
		return 0;
	}
	astChildVari = stVariableInfoAccess.child.get( astVari );
	while( value.u8Remainder > 0 && astChildVari > 0 ){
		astChildVari = stVariableInfoAccess.next.get( astChildVari );
		value.u8Remainder--;
	}
	return astChildVari;
}
